#include "factory.h"

#include <cassert>

#include <fstream>

#include "util/logger/logger.h"


namespace html::tmplt
{

static std::string makeTitle(const std::string &rootDir) {
    std::string result("html::tmplt::Factory(");
    result.append(fs::absolute(rootDir).lexically_normal().generic_string());
    result.append(") ");
    return result;
}

Factory::Factory(const std::string &rootDir)
    : title_(makeTitle(rootDir)), rootDir_(rootDir) {

    LOGD << title() << "constructed";
}

Factory::~Factory() {
    LOGD << title() << "destructed";
}

const Template *Factory::byPath(const std::string &relativePath) {
    const fs::path fullPath = (rootDir_ / relativePath).lexically_normal();
    if (!fs::exists(fullPath)) {
        LOGE << title() << "file not exists: [" << fullPath.generic_string() << "]";
        return nullptr;
    }

    const auto it = map_.find(relativePath);
    if (it != map_.end()) {
        assert(it->second);
        const TemplateCache &cache = *(it->second);
        if (!cache.get().isOutdated(cache.timestamp())) {
            return &(cache.get());
        } else {
            map_.erase(it);
            LOGD << title() << "template file [" << fullPath << "] modified, reload it.";
        }
    }

    if (fs::is_directory(fullPath)) {
        LOGE << title() << "path is a directory: [" << fullPath.generic_string() << "]";
        return nullptr;
    }

    TemplateCache *newTemplate = new TemplateCache(fullPath, fs::last_write_time(fullPath));
    map_[relativePath] = std::shared_ptr<TemplateCache>(newTemplate);

    LOGD << title() << "http template cached, name: ["
        << relativePath << "], file: [" << fullPath.generic_string() << "]";

    return &(newTemplate->get());
}

} // namespace html::tmplt
